#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "util.h"

// 全局常量, 字符串, 用于日志打印的标签
const static char* TAG = "priority_inversion";

// 全局变量, 信号量
static SemaphoreHandle_t semphr = NULL;

// 高优先级任务
static void highTask(void* arg)
{  
    // 延时1s
    vTaskDelay(pdMS_TO_TICKS(2000));
    // 日志打印
    MY_LOGI("highTask waiting...");
    // 堵塞获取信号量
    if(xSemaphoreTake(semphr, portMAX_DELAY)) {
        // 日志打印
        MY_LOGI("highTask take semaphore, do something for 3 second");
        // 延时3s
        vTaskDelay(pdMS_TO_TICKS(3000));  
        // 日志打印  
        MY_LOGI("highTask done, release semaphore"); 
        // 释放信号量   
        xSemaphoreGive(semphr);
    }
    vTaskDelete(NULL);
}

// 中优先级任务
static void middleTask(void* arg)
{
    // 延时3s
    vTaskDelay(pdMS_TO_TICKS(3000));  
    // 日志打印
    MY_LOGI("middleTask do something for 10 second");
    // 硬延时10s
    delay_ms_cpu(10000);  
    // 日志打印
    MY_LOGI("middleTask done");
    vTaskDelete(NULL);
}

// 低优先级任务
static void lowTask(void* arg)
{
    // 延时1s
    vTaskDelay(pdMS_TO_TICKS(1000));
    // 堵塞获取信号量
    if(xSemaphoreTake(semphr, portMAX_DELAY)) {
        // 日志打印
        MY_LOGI("lowTask take semaphore, do something for 3 second");
        // 延时3s
        vTaskDelay(pdMS_TO_TICKS(3000));  
        // 日志打印  
        MY_LOGI("lowTask done, release semaphore"); 
        // 释放信号量   
        xSemaphoreGive(semphr);
    }
    vTaskDelete(NULL);
}

void app_main(void)
{
    //创建1个二值信号量
    semphr = xSemaphoreCreateBinary();

    //先释放信号量
    xSemaphoreGive(semphr);

    //创建1个任务，堆栈大小4096，优先级6，数值越大优先级越高
    xTaskCreate(highTask, "highTask", 4096, NULL, 6, NULL);

    //创建1个任务，堆栈大小4096，优先级5，数值越大优先级越高
    xTaskCreate(middleTask, "middleTask",  4096, NULL, 5,  NULL);

    //创建1个任务，堆栈大小4096，优先级5，数值越大优先级越高
    xTaskCreate(lowTask, "lowTask",  4096, NULL, 4,  NULL);
}